package com.yourbatis.lexical;

import com.yourbatis.syntax.Keywords;

import java.util.ArrayList;
import java.util.List;

import static javax.lang.model.SourceVersion.isKeyword;

public class Lexer {
    private String input; // 输入字符串
    private int position; // 当前字符位置
    private char currentChar; // 当前字符

    public Lexer(String input) {
        this.input = input;
        this.position = 0;
        this.currentChar = input.charAt(position);
    }

    // 读取下一个字符
    private void advance() {
        position++;
        if (position < input.length()) {
            currentChar = input.charAt(position);
        } else {
            currentChar = '\0'; // 文件结束
        }
    }

    /**
     * 预读下一个字符
     */
    private char peek() {
        int nextPosition = position + 1;
        if (nextPosition < input.length()) {
            return input.charAt(nextPosition);
        } else {
            return '\0'; // 文件结束
        }
    }

    // 跳过空白字符
    private void skipWhitespace() {
        while (currentChar != '\0' && currentChar != '\n' && Character.isWhitespace(currentChar)) {
            advance();
        }
    }

    // 读取数字
    private String readNumber() {
        StringBuilder result = new StringBuilder();
        while (currentChar != '\0' && Character.isDigit(currentChar)) {
            result.append(currentChar);
            advance();
        }
        return result.toString();
    }

    // 读取标识符或关键字
    private String readIdentifier() {
        StringBuilder result = new StringBuilder();
        while (currentChar != '\0' && Character.isLetterOrDigit(currentChar)) {
            result.append(currentChar);
            advance();
        }
        return result.toString();
    }

    private String readSymbols(String symbols) {
        StringBuilder result = new StringBuilder();
//        String symbols = "><=!";
        while (currentChar != '\0' && symbols.indexOf(currentChar) > -1) {
            result.append(currentChar);
            advance();
        }
        return result.toString();
    }

    // 获取下一个标记
    public Token getNextToken() {
        while (currentChar != '\0') {

            if (!isLineBreak(currentChar) && Character.isWhitespace(currentChar)) {
                skipWhitespace();
                continue;
            }

            if (Character.isDigit(currentChar)) {
                return new Token(TokenType.NUMBER, readNumber());
            }

            if (Character.isLetter(currentChar)) {
                String identifier = readIdentifier();
                // 检查是否为关键字
                if (Keywords.isKeyword(identifier)) {
                    return new Token(TokenType.KEYWORD, identifier);
                } else {
                    return new Token(TokenType.IDENTIFIER, identifier);
                }
            }
            char peek = peek();
            if (currentChar == '+' && peek == '+' || currentChar == '-' && peek == '-') {
                Token token = new Token(TokenType.OPERATOR, String.valueOf(currentChar) + peek);
                advance();
                advance();
                return token;
            }
            if (isOperator(currentChar) && peek != '=') {
                Token token = new Token(TokenType.OPERATOR, String.valueOf(currentChar));
                advance();
                return token;
            }

            if (isDelimiter(currentChar)) {
                Token token = new Token(TokenType.DELIMITER, String.valueOf(currentChar));
                advance();
                return token;
            }

            if (isLineBreak(currentChar)) {
                Token token = new Token(TokenType.DELIMITER, String.valueOf(currentChar));
                advance();
                return token;
            }
            if (isBracket(currentChar)) {
                Token token = new Token(TokenType.DELIMITER, String.valueOf(currentChar));
                advance();
                return token;
            }

            if (isCompare(currentChar)) {
                String read = readSymbols("><=!");
                if("=".equals(read) && peek == '='){
                    read = read + peek;
                    advance();
                }
                Token token = new Token(TokenType.COMPARISON, read);
                return token;
            }

            if (isLogical(currentChar)) {
                String read = readSymbols("&|");
                Token token = new Token(TokenType.LOGICAL, read);
                return token;
            }
            if(currentChar == '\''){
                advance();
                String read = readIdentifier();
                Token token = new Token(TokenType.STRING, read);
                advance();
                return token;
            }


            throw new RuntimeException("Unknown character: " + currentChar);
        }

        return new Token(TokenType.EOF, "");
    }

    private boolean isLogical(char ch) {
        return ch == '&' || ch == '|';
    }

    private boolean isCompare(char ch) {
        return ch == '>' || ch == '<' || ch == '=' || ch == '!';
    }

    private boolean isBracket(char ch) {
        return ch == '(' || ch == ')' || ch == '{' || ch == '}';
    }

    // 判断是否为关键字


    // 判断是否为运算符
    private boolean isOperator(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=';
    }

    // 判断是否为分隔符
    private boolean isDelimiter(char ch) {
        return ch == ';' || ch == ',';
    }

    // 换行符
    private boolean isLineBreak(char ch) {
        return ch == '\n';
    }

    // 获取所有标记
    public List<Token> tokenize() {
        List<Token> tokens = new ArrayList<>();
        Token token = getNextToken();
        while (token.getType() != TokenType.EOF) {
            tokens.add(token);
            token = getNextToken();
        }
//        if(!tokens.isEmpty() && !tokens.get(tokens.size()-1).getType().equals(TokenType.DELIMITER)){
//            tokens.add(new Token(TokenType.DELIMITER,";"));
//        }
        tokens.add(token); // 添加EOF标记
        return tokens;
    }
}
